package com.leyou.gateway.filter;

import com.leyou.common.auth.pojo.Payload;
import com.leyou.common.auth.pojo.UserInfo;
import com.leyou.common.auth.utils.JwtUtils;
import com.leyou.common.constants.LyConstants;
import com.leyou.common.exception.pojo.ExceptionEnum;
import com.leyou.common.exception.pojo.LyException;
import com.leyou.common.utils.CookieUtils;
import com.leyou.gateway.config.FilterProperties;
import com.leyou.gateway.config.JwtProperties;
import com.leyou.gateway.scheduler.AppTokenScheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * 权限控制过滤器
 */
@Component
public class AuthFilter implements GlobalFilter,Ordered{

    @Autowired
    private JwtProperties jwtProps;

    @Autowired
    private FilterProperties filterProps;

    @Autowired
    private AppTokenScheduler appTokenScheduler;
    /**
     * 编写过滤逻辑
     * @param exchange： 封装了request和response对象
     * @param chain 过滤器链，控制过滤器的流程。用于执行后面的过滤器或者执行目标资源
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //1.从request取出Cookie中token值

        //ServerHttpRequest: Spring封装的request对象。和之前Servlet的HttpServletRequest不一样。是Spring重新封装出来的一个API
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();

        //往网关路由的请求头添加服务token
        request.mutate().header(LyConstants.APP_TOKEN_HEADER,appTokenScheduler.getAppToken());


        //加入白名单判断
        //1.获取当前访问的URL路径
        String uri = request.getURI().getPath(); // 如： /api/item/category/of/parent

        //2.判断当前访问路径是否在白名单列表中
        List<String> allowPaths = filterProps.getAllowPaths();
        for(String allowPath:allowPaths){ // /api/item
            if(uri.contains(allowPath)){
                // //3.如果在，直接放行了
                return chain.filter(exchange);
            }
        }

        //2.校验token的合法性
        Payload<UserInfo> payload = null;
        try {
            //getCookies(): 取出所有Cookie
            //getFirst(): 取出指定名称的第一个Cookie
            //getValue(): 取出Cookie的值
            String token = request.getCookies().getFirst(jwtProps.getCookie().getCookieName()).getValue();
            payload = JwtUtils.getInfoFromToken(token, jwtProps.getPublicKey(), UserInfo.class);
        } catch (Exception e) {
           //throw new LyException(ExceptionEnum.UNAUTHORIZED);
            //给用户返回401状态码
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            //中止请求
            return response.setComplete();

        }

        //TODO: 查询当前用户拥有的权限（基于RBAC表查询得到），判断用户是否有足够权限访问

        //放行请求
        return chain.filter(exchange);
    }

    /**
     * 配置当前过滤器访问优先级
     * 返回数字，数字越大，优先级越小
     * 注意： 自定义过滤器的优先级一般不要写10000以后的
     * @return
     */
    @Override
    public int getOrder() {
        return 1;
    }
}
